/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.base.service.impl;

import com.xy.biz.base.client.EquipmentClient;
import com.xy.biz.base.client.GoodsClient;
import com.xy.biz.base.domain.bo.BomBO;
import com.xy.biz.base.domain.bo.BomEquipmentBO;
import com.xy.biz.base.domain.bo.BomGoodsBO;
import com.xy.biz.base.domain.query.BomByIdQuery;
import com.xy.biz.base.domain.query.BomQuery;
import com.xy.biz.base.domain.resp.GetEquipmentResponse;
import com.xy.biz.base.domain.resp.GetGoodsResponse;
import com.xy.biz.base.manager.BomManager;
import com.xy.biz.base.service.BomService;
import com.xy.lang.domain.Result;
import com.xy.lang.domain.tuples.Pair;
import com.xy.lang.enums.ApplyStatusEnum;
import com.xy.lang.util.ResultUtils;
import com.xy.tool.context.UserContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zsp
 * @date 2021-12-28
 */
@Service("bomService")
public class BomServiceImpl implements BomService {

    @Autowired
    private BomManager bomManager;
    @Autowired
    private GoodsClient goodsClient;
    @Autowired
    private EquipmentClient equipmentClient;

    @Override
    public Result<?> saveBom(BomBO bomBO) {
        Result<Pair<Map<Long, GetGoodsResponse>, Map<Long, GetEquipmentResponse>>> result = getGoodsAndEquipmentMap(bomBO);
        if (!result.wasSuccess()) {
            return result;
        }
        Map<Long, GetGoodsResponse> goodsMap = result.getData().getValue1();
        Map<Long, GetEquipmentResponse> equipmentMap = result.getData().getValue2();
        buildBom(bomBO, goodsMap, equipmentMap);
        if (CollectionUtils.isEmpty(bomBO.getGoodsList())) {
            return Result.ofBadRequest();
        }
        int affectedRows = bomManager.saveBom(bomBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        if (affectedRows == -1) {
            return Result.ofBadRequest("此货号信息已存在启用数据");
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> updateBom(BomBO bomBO) {
        BomBO bom = bomManager.getBom(BomByIdQuery.builder().bomId(bomBO.getBomId()).build());
        if (Objects.isNull(bom)) {
            return Result.ofNotFound(String.valueOf(bomBO.getBomId()));
        }
        Result<Pair<Map<Long, GetGoodsResponse>, Map<Long, GetEquipmentResponse>>> result = getGoodsAndEquipmentMap(bomBO);
        if (!result.wasSuccess()) {
            return result;
        }
        Map<Long, GetGoodsResponse> goodsMap = result.getData().getValue1();
        Map<Long, GetEquipmentResponse> equipmentMap = result.getData().getValue2();
        buildBom(bomBO, goodsMap, equipmentMap);
        int affectedRows = bomManager.updateBom(bomBO);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofBadRequest("此产品已存在启用数据！");
    }

    @Override
    public Result<?> auditBom(BomBO bomBO) {
        BomBO bom = bomManager.getBom(BomByIdQuery.builder().bomId(bomBO.getBomId()).build());
        if (Objects.isNull(bom)) {
            return Result.ofNotFound(String.valueOf(bomBO.getBomId()));
        }
        bomBO.setAuditUserId(UserContextHolder.getUserId());
        bomBO.setAuditUserName(UserContextHolder.getUserName());
        bomBO.setAuditTime(LocalDateTime.now());
        bomBO.setUpdateUserId(UserContextHolder.getUserId());
        bomBO.setUpdateUserName(UserContextHolder.getUserName());
        bomBO.setUpdateTime(LocalDateTime.now());
        int row = bomManager.auditBom(bomBO);
        if (row > 0) {
            return Result.success();
        }
        return Result.fail();
    }

    @Override
    public Result<?> copyBom(Long bomId) {
        BomBO bom = bomManager.getBom(BomByIdQuery.builder().bomId(bomId).build());
        if (Objects.isNull(bom)) {
            return Result.ofNotFound(String.valueOf(bomId));
        }
        int row = bomManager.copyBom(bom);
        if (row > 0) {
            return Result.success();
        }
        if (row == -1) {
            return Result.ofBadRequest("当前物料清单暂无货品明细！");
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public Result<?> deleteBom(Long bomId) {
        BomBO bom = bomManager.getBom(BomByIdQuery.builder().bomId(bomId).build());
        if (Objects.isNull(bom)) {
            return Result.ofNotFound(String.valueOf(bomId));
        }
        int affectedRows = bomManager.deleteBom(bomId);
        if (affectedRows > 0) {
            return Result.success();
        }
        return Result.ofErrorRowsAffected();
    }

    @Override
    public BomBO getBom(BomByIdQuery query) {
        return bomManager.getBom(query);
    }

    @Override
    public List<BomBO> listBomById(Collection<Long> collection) {
        return bomManager.listBomById(collection);
    }

    @Override
    public List<BomBO> listBom(BomQuery query) {
        return bomManager.listBom(query);
    }

    @Override
    public int countBom(BomQuery query) {
        return bomManager.countBom(query);
    }

    private Result<Pair<Map<Long, GetGoodsResponse>, Map<Long, GetEquipmentResponse>>> getGoodsAndEquipmentMap(BomBO bomBO) {
        Set<Long> goodsIdSet = new HashSet<>();
        if (Objects.nonNull(bomBO.getGoodsId())) {
            goodsIdSet.add(bomBO.getGoodsId());
        }
        if (!CollectionUtils.isEmpty(bomBO.getGoodsList())) {
            for (BomGoodsBO bomGoods : bomBO.getGoodsList()) {
                goodsIdSet.add(bomGoods.getGoodsId());
            }
        }
        Set<Long> equipmentIdSet = new HashSet<>();
        if (!CollectionUtils.isEmpty(bomBO.getEquipmentList())) {
            for (BomEquipmentBO bomEquipment : bomBO.getEquipmentList()) {
                equipmentIdSet.add(bomEquipment.getEquipmentId());
            }
        }
        List<GetGoodsResponse> goodsList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(goodsIdSet)) {
            goodsList = ResultUtils.get(goodsClient.listGoodsById(goodsIdSet));
        }
        List<GetEquipmentResponse> equipmentList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(equipmentIdSet)) {
            equipmentList = ResultUtils.get(equipmentClient.listEquipmentById(equipmentIdSet));
        }
        if (!Objects.equals(goodsIdSet.size(), goodsList.size())) {
            goodsIdSet.removeAll(goodsList.stream().map(GetGoodsResponse::getGoodsId).collect(Collectors.toSet()));
            return Result.ofNotFound("不存在的货品：" + goodsIdSet);
        }
        if (!Objects.equals(equipmentIdSet.size(), equipmentList.size())) {
            equipmentIdSet.removeAll(equipmentList.stream().map(GetEquipmentResponse::getEquipmentId).collect(Collectors.toSet()));
            return Result.ofNotFound("不存在的设备：" + equipmentIdSet);
        }
        Map<Long, GetGoodsResponse> goodsMap = goodsList.stream().collect(Collectors.toMap(GetGoodsResponse::getGoodsId, e -> e));
        Map<Long, GetEquipmentResponse> equipmentMap = equipmentList.stream().collect(Collectors.toMap(GetEquipmentResponse::getEquipmentId, e -> e));
        return Result.success(new Pair<>(goodsMap, equipmentMap));
    }

    private void buildBom(BomBO bomBO, Map<Long, GetGoodsResponse> goodsMap, Map<Long, GetEquipmentResponse> equipmentMap) {
        LocalDateTime now = LocalDateTime.now();
//        if (Objects.isNull(bomBO.getStatus())) {
//            bomBO.setStatus(ApplyStatusEnum.DRAFT.getCode());
//        }
        bomBO.setStatus(ApplyStatusEnum.START.getCode());

        if (Objects.isNull(bomBO.getAuditStatus())) {
            bomBO.setAuditStatus(0);
        }
        bomBO.setTenantId(UserContextHolder.getTenantId());
        bomBO.setCreateUserId(UserContextHolder.getUserId());
        bomBO.setCreateUserName(UserContextHolder.getUserName());
        bomBO.setCreateTime(now);
        bomBO.setUpdateUserId(UserContextHolder.getUserId());
        bomBO.setUpdateUserName(UserContextHolder.getUserName());
        bomBO.setUpdateTime(now);
        if (!CollectionUtils.isEmpty(goodsMap)) {
            GetGoodsResponse goods = goodsMap.get(bomBO.getGoodsId());
            if (Objects.nonNull(goods)) {
                bomBO.setGoodsCode(goods.getGoodsCode());
                bomBO.setGoodsFullCode(goods.getGoodsFullCode());
                bomBO.setGoodsAbbr(goods.getGoodsAbbr());
                bomBO.setCategory(goods.getCategory());
            }
            if (!CollectionUtils.isEmpty(bomBO.getGoodsList())) {
                for (BomGoodsBO bomGoods : bomBO.getGoodsList()) {
                    goods = goodsMap.get(bomGoods.getGoodsId());
                    bomGoods.setGoodsCode(goods.getGoodsCode());
                    bomGoods.setGoodsFullCode(goods.getGoodsFullCode());
                    bomGoods.setGoodsAbbr(goods.getGoodsAbbr());
                    bomGoods.setTenantId(UserContextHolder.getTenantId());
                    bomGoods.setUpdateTime(now);
                }
            }
        }
        if (!CollectionUtils.isEmpty(bomBO.getEquipmentList()) && !CollectionUtils.isEmpty(equipmentMap)) {
            for (BomEquipmentBO bomEquipment : bomBO.getEquipmentList()) {
                GetEquipmentResponse getEquipmentResponse = equipmentMap.get(bomEquipment.getEquipmentId());
                bomEquipment.setEquipmentCode(getEquipmentResponse.getEquipmentCode());
                bomEquipment.setEquipmentName(getEquipmentResponse.getEquipmentName());
                bomEquipment.setTenantId(UserContextHolder.getTenantId());
                bomEquipment.setUpdateTime(LocalDateTime.now());
            }
        }
    }

}
